import fitz

from app.utils.pymupdf_tools import extract_json, pdf_get_content_region, replace_text_with_image_in_roi, insert_image_by_roi
from tests.base_test import base_test_case

logger = base_test_case.get_logger(__name__)
TEST_DATA_DIR = base_test_case.test_data_dir
OUTPUT_DATA_DIR = base_test_case.output_data_dir


def extract_text_with_zoom(pdf_path, page_number=0, zoom_factor=2.0):
    """
    以指定缩放因子提取PDF页面文本和坐标

    Args:
        pdf_path: PDF文件路径
        page_number: 页面编号（从0开始）
        zoom_factor: 缩放因子

    Returns:
        list: 包含文本块和坐标的列表，每个元素为 (x0, y0, x1, y1, text)
    """
    # 打开PDF文件
    doc = fitz.open(pdf_path)
    page = doc[page_number]

    # 创建缩放矩阵
    mat = fitz.Matrix(zoom_factor, zoom_factor)
    # 获取详细文本信息
    text_dict = page.get_text("dict")
    # 提取文本块（使用缩放后的坐标）
    blocks = page.get_text("blocks")
    # blocks = page.get_text("blocks", matrix=mat)

    # 处理文本块
    text_blocks = []
    for block in blocks:
        x0, y0, x1, y1, text, block_no, block_type = block
        # text可能包含多个文本行，需要清理
        text = text.strip()
        if text:  # 只添加非空文本
            # 坐标已经是缩放后的坐标
            text_blocks.append((x0, y0, x1, y1, text))

    doc.close()
    return text_blocks


def extract_text_with_zoom_detailed(pdf_path, page_number=0, zoom_factor=2.0):
    """
    使用详细模式提取文本和坐标
    """
    doc = fitz.open(pdf_path)
    page = doc[page_number]

    # 获取详细文本信息
    text_dict = page.get_text("dict")

    text_blocks = []
    # 遍历所有文本块
    for block in text_dict["blocks"]:
        if "lines" in block:  # 确保是文本块而不是图像块
            # 获取块的边界框
            bbox = block["bbox"]
            x0, y0, x1, y1 = bbox

            # 收集块内所有文本
            block_text = ""
            for line in block["lines"]:
                for span in line["spans"]:
                    block_text += span["text"]

            # 应用缩放因子
            x0, y0, x1, y1 = x0 * zoom_factor, y0 * zoom_factor, x1 * zoom_factor, y1 * zoom_factor

            if block_text.strip():
                text_blocks.append((x0, y0, x1, y1, block_text.strip()))

    doc.close()
    return text_blocks


def extract_text_with_zoom_v2(pdf_path, page_number=0, zoom_factor=2.0):
    """
    以指定缩放因子提取PDF页面文本和坐标

    Args:
        pdf_path: PDF文件路径
        page_number: 页面编号（从0开始）
        zoom_factor: 缩放因子

    Returns:
        list: 包含文本块和坐标的列表，每个元素为 (x0, y0, x1, y1, text)
    """
    # 打开PDF文件
    doc = fitz.open(pdf_path)
    page = doc[page_number]

    text = page.get_text()
    blocks = page.get_text('blocks', sort=True)
    dict = page.get_text('dict', sort=True)
    words = page.get_text('words')
    rawdict = page.get_text('rawdict')
    rawjson = page.get_text('rawjson')
    json = page.get_text('json')
    html = page.get_text('html')
    xhtml = page.get_text('xhtml')
    xml = page.get_text('xml')
    text = page.get_text('text')

    # 创建缩放矩阵
    mat = fitz.Matrix(zoom_factor, zoom_factor)

    # 使用缩放矩阵创建TextPage
    textpage = page.get_textpage(matrix=mat)

    # 从TextPage提取文本块
    blocks = textpage.extractBLOCKS()

    # 处理文本块
    text_blocks = []
    for block in blocks:
        x0, y0, x1, y1, text, block_no, block_type = block
        # text可能包含多个文本行，需要清理
        text = text.strip()
        if text:  # 只添加非空文本
            # 坐标已经是应用缩放后的坐标
            text_blocks.append((x0, y0, x1, y1, text))

    doc.close()
    return text_blocks


def extract_text_dict_with_zoom(pdf_path, page_number=0, zoom_factor=2.0):
    """
    使用 page.get_text('dict', sort=True) 方法提取文本和坐标，并应用缩放因子
    
    Args:
        pdf_path: PDF文件路径
        page_number: 页面编号（从0开始）
        zoom_factor: 缩放因子

    Returns:
        dict: 包含缩放后坐标的详细文本信息
    """
    # 打开PDF文件
    doc = fitz.open(pdf_path)
    page = doc[page_number]

    # 获取详细文本信息
    text_dict = page.get_text("dict", sort=True)

    # 应用缩放因子到所有坐标
    scaled_text_dict = {
        "width": text_dict.get("width", 0) * zoom_factor,
        "height": text_dict.get("height", 0) * zoom_factor,
        "blocks": []
    }

    # 遍历所有文本块
    for block in text_dict.get("blocks", []):
        # 复制块信息
        scaled_block = block.copy()

        # 缩放块的边界框
        if "bbox" in scaled_block:
            x0, y0, x1, y1 = scaled_block["bbox"]
            scaled_block["bbox"] = [x0 * zoom_factor, y0 * zoom_factor, x1 * zoom_factor, y1 * zoom_factor]

        # 处理块中的行
        if "lines" in scaled_block:
            for line in scaled_block["lines"]:
                # 缩放行的边界框
                if "bbox" in line:
                    x0, y0, x1, y1 = line["bbox"]
                    line["bbox"] = [x0 * zoom_factor, y0 * zoom_factor, x1 * zoom_factor, y1 * zoom_factor]

                # 处理行中的跨度
                if "spans" in line:
                    for span in line["spans"]:
                        # 缩放跨度的边界框
                        if "bbox" in span:
                            x0, y0, x1, y1 = span["bbox"]
                            span["bbox"] = [x0 * zoom_factor, y0 * zoom_factor, x1 * zoom_factor, y1 * zoom_factor]

                        # 处理跨度中的字符（如果存在）
                        if "chars" in span:
                            for char in span["chars"]:
                                if "bbox" in char:
                                    x0, y0, x1, y1 = char["bbox"]
                                    char["bbox"] = [x0 * zoom_factor, y0 * zoom_factor, x1 * zoom_factor, y1 * zoom_factor]

        # 处理图像块（如果存在）
        if block.get("type") == 1:  # 图像块
            if "bbox" in scaled_block:
                x0, y0, x1, y1 = scaled_block["bbox"]
                scaled_block["bbox"] = [x0 * zoom_factor, y0 * zoom_factor, x1 * zoom_factor, y1 * zoom_factor]

        scaled_text_dict["blocks"].append(scaled_block)

    doc.close()
    return scaled_text_dict


def apply_page_dict_to_pdf(page, new_page_dict, removed_blocks):
    """
    将修改后的page_dict应用到PDF页面上

    Args:
        page: PyMuPDF文档 page 对象
        new_page_dict: 修改后的页面dict数据
        removed_blocks: 被删除的块列表

    Returns:
        None
    """

    # 用白色矩形覆盖被删除的文本块
    for block in removed_blocks:
        if block.get('type') == 0:  # 只处理文本块
            bbox = block.get('bbox')
            rect = fitz.Rect(bbox)
            page.draw_rect(rect, color=(1, 1, 1), fill=(1, 1, 1))

    # 查找新增的图片块并插入图片
    for block in new_page_dict.get('blocks', []):
        if block.get('type') == 1 and 'image_path' in block:  # 图片块且有图片路径
            bbox = block.get('bbox')
            rect = fitz.Rect(bbox)
            # 插入图片
            page.insert_image(rect, filename=block['image_path'], keep_proportion=False)


if __name__ == '__main__':
    """文本提取方法："""
    # dict = page.get_text('dict', sort=True)
    # text = page.get_text()
    # blocks = page.get_text('blocks', sort=True)
    # words = page.get_text('words')
    # rawdict = page.get_text('rawdict')
    # rawjson = page.get_text('rawjson')
    # json = page.get_text('json')
    # html = page.get_text('html')
    # xhtml = page.get_text('xhtml')
    # xml = page.get_text('xml')
    # text = page.get_text('text')
    # 使用示例
    pdf_path = str(TEST_DATA_DIR / "25-注会-轻1-财务成本管理[上册](第3章).pdf")
    # roi_bbox = (237.46, 137.87, 295.46, 177.44)  # 文本
    """对比缩放的情况测试"""
    # zoom_factor = 2.0  # 放大2倍
    # # text_blocks = extract_text_with_zoom(pdf_path, page_number=0, zoom_factor=zoom_factor)
    # # text_blocks = extract_text_with_zoom_v2(pdf_path, page_number=0, zoom_factor=zoom_factor)
    #
    # # 测试新的 extract_text_dict_with_zoom 函数
    # print("测试 extract_text_dict_with_zoom 函数:")
    # try:
    #     scaled_dict = extract_text_dict_with_zoom(pdf_path, page_number=0, zoom_factor=zoom_factor)
    #     print(f"页面尺寸 (缩放后): {scaled_dict['width']:.2f} x {scaled_dict['height']:.2f}")
    #     print(f"找到 {len(scaled_dict['blocks'])} 个块")
    #
    #     # 显示前几个文本块的信息
    #     text_blocks = [block for block in scaled_dict['blocks'] if block.get('type', 0) == 0]  # 只显示文本块
    #     for i, block in enumerate(text_blocks[:3]):
    #         bbox = block.get('bbox', [])
    #         if bbox:
    #             x0, y0, x1, y1 = bbox
    #             text = ""
    #             # 收集块中的文本
    #             if 'lines' in block:
    #                 for line in block['lines']:
    #                     if 'spans' in line:
    #                         for span in line['spans']:
    #                             text += span.get('text', '')
    #
    #             print(f"  块 {i + 1}: 坐标=({x0:.2f}, {y0:.2f}, {x1:.2f}, {y1:.2f}), 文本='{text[:50]}{'...' if len(text) > 50 else ''}")
    # except Exception as e:
    #     print(f"测试 extract_text_dict_with_zoom 函数时出错: {e}")
    #
    # # 对比不缩放的情况
    # print("\n对比原始坐标:")
    # try:
    #     original_dict = extract_text_dict_with_zoom(pdf_path, page_number=0, zoom_factor=1.0)
    #     text_blocks = [block for block in original_dict['blocks'] if block.get('type', 0) == 0]  # 只显示文本块
    #     for i, block in enumerate(text_blocks[:3]):
    #         bbox = block.get('bbox', [])
    #         if bbox:
    #             x0, y0, x1, y1 = bbox
    #             text = ""
    #             # 收集块中的文本
    #             if 'lines' in block:
    #                 for line in block['lines']:
    #                     if 'spans' in line:
    #                         for span in line['spans']:
    #                             text += span.get('text', '')
    #
    #             print(f"  块 {i + 1}: 坐标=({x0:.2f}, {y0:.2f}, {x1:.2f}, {y1:.2f}), 文本='{text[:50]}{'...' if len(text) > 50 else ''}")
    # except Exception as e:
    #     print(f"获取原始坐标时出错: {e}")
    """    测试 pdf页面信息,按 roi_bbox 区域替换图片    """
    # 打开PDF文件
    doc = fitz.open(pdf_path)
    page = doc[1]
    # 获取正文
    text_dict = page.get_text('dict', clip=pdf_get_content_region(page, zoom_factor=1.0), sort=True)
    # extract_json(text_dict, output_path=OUTPUT_DATA_DIR / "page_1_image_source.json")# 保存正文原始数据
    image_roi_bbox = (431.0463562011719, 174.14712524414062, 467.5277099609375, 211.62847900390625)  # 图像
    # 修改正文指定的roi区域内容替换图片
    new_text_dict, removed_blocks, _ = replace_text_with_image_in_roi(
        text_dict,
        image_roi_bbox,
        is_only_process_blocks_text=False,
        verbose=True,
        image_path=TEST_DATA_DIR / "seal.png",
        # image_path=TEST_DATA_DIR / "textline.png"
    )
    # 保存修改后的正文数据
    extract_json(new_text_dict, sort=True, output_path=OUTPUT_DATA_DIR / "modified_pdf.json")

    # 将修改应用到PDF页面
    apply_page_dict_to_pdf(page, new_text_dict, removed_blocks)
    insert_image_by_roi(page, image_roi_bbox, image_path=TEST_DATA_DIR / "seal.png")
    # 保存修改后的PDF
    doc.save(OUTPUT_DATA_DIR / "modified_pdf.pdf")

    doc.close()

    """ 测试矩形相交 """
    # # 创建两个矩形
    # rect1 = fitz.Rect(0, 0, 100, 100)
    # rect2 = fitz.Rect(50, 50, 150, 150)
    #
    # # 使用PyMuPDF内置方法判断是否相交
    # if rect1.intersects(rect2):
    #     print("两个矩形相交")
    #
    # # 或者使用 & 操作符获取交集
    # intersection = rect1 & rect2
    # if intersection:
    #     print("两个矩形相交，交集区域为:", intersection)
    #     intersection_area = intersection.width * intersection.height
    #     print("交集区域的面积:", intersection_area)
    #     # 计算并集
    #     union = rect1 | rect2
    #     union_area = union.width * union.height
    #     print(f"并集区域: {union}")
    #     print(f"并集面积: {union_area}")
    #
    #     # 计算IoU
    #     iou = intersection_area / union_area if union_area > 0 else 0
    #     print(f"IoU (交并比): {iou:.2f}")
    # else:
    #     print("两个矩形不相交")

    """ 测试 extract_json """
    # doc = fitz.open(pdf_path)
    # page = doc[0]
    # text = page.get_text()
    # # blocks = page.get_text('blocks', sort=True)
    # dict = page.get_text('dict', sort=True)
    # json = extract_json(dict, sort=True)
    # print(json)
    # doc.close()
